/**
 * 
 */
package es.uab.es2.TimeTracker.nucli;

import java.util.Observable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Date;

//import org.apache.log4j.Logger;

/**
 * Classe que simula la funcionalitat d'un rellotge, cronometra intervals.
 * Aquesta classe deriva de la classe {@link Obserbable}, 
 * Cada vegada que passen 2 segons i el rellotge canvia d'estat ho 
 * notifica a tots els observadors que tingui en aquell moment.
 * @author Jes�s Berm�dez, Ricard Figueras i Abel Rodr�guez
 */
public final class Rellotge extends Observable {

    
    //********************** Constructors **********************
    
    	
		/** 
		 * 
		 * Inicilitza el rellotge a -1.
		 * L'acci� al constructor �s privat per garantizar que nom�s es 
		 * crea un objecte de la classe Rellotge.
		 * 
		 */
		private Rellotge() {
		
		    timer = null;
		    on = false;
		    temps = -1;  }
    
    //********************** Atributs **********************
    
    /**
     * Indica en quina 
     * mesura de temps, aquest relloge notifica als
     * Observers.
     * @uml.property  name="INTERVALO_MS"
     */
    private static final long INTERVALO_MS = 2000;
	

	/**
	 * Controla si el rollotge est� actiu o no.
	 * Es considera el interruptor del rellotge.
	 * @uml.property  name="on"
	 */
	private boolean on = false;
	
	/**
	 * Realitza una tasca paral�lela.
	 * a la execuci� de l'aplicaci� a partir d'un TimerTask 
	 * durant un cert periode;
     * @uml.property  name="timer"
     */
    private Timer timer;
    
    /** 
     * Encarregat de enmagatzemar el temps d'execuci� 
     * cada 2 segons durant el temps que el rellotge
     * estigui en execuci�.
	 * @uml.property name="temps"
	 */
    private long temps = 0;
    

    /**
     * Encarregat de incrementar el pas dels segons
     * del rellotge per despres ser recollit en els
     * intervals.
     * @uml.property  name="intervalo_mS"
     */
    private static long intervaloMS = 0;
    
    /**
     * Encarregat de contenir la data actual
     * Aquesta data s'actualitza cada 2 segons 
     * i es recollida per els intervals observadors.
     *  @uml.property  name="data_actual"
     */
    private static Date dataActual;
    
    private static Date dataInicial = null;
    
	
	 //********************** Getters & Setters **********************
	/**
     * Getter of the property <tt>on</tt>.
     * @return  Returns the on.
     * @uml.property  name="on"
     */
    public boolean isOn() {
		return on;
	}

    /**
     * Setter of the property <tt>on</tt>.
     * @param on  The on to set.
     * @uml.property  name="on"
     */
    public void setOn(final boolean bOn) {
		this.on = bOn;
	}

	/**
	 * Getter of the property <tt>timer</tt>.
	 * @return  Returns the timer.
	 * @uml.property  name="timer"
	 */
	public Timer getTimer() {
		return timer;
	}

	/**
	 * Setter of the property <tt>timer</tt>.
	 * @param timer  The timer to set.
	 * @uml.property  name="timer"
	 */
	public void setTimer(final Timer tTimer) {
		this.timer = tTimer;
	}

	/** 
	 * Getter of the property <tt>temps</tt>.
	 * @return  Returns the temps.
	 * @uml.property  name="temps"
	 */
	public long getTemps() {
		return temps;
	}

	/** 
	 * Setter of the property <tt>temps</tt>.
	 * @param temps  The temps to set.
	 * @uml.property  name="temps"
	 */
	public void setTemps(final long lTemps) {
		this.temps = lTemps;
	}

	/**
     * Getter of the property <tt>intervalo</tt>.
     * @return  Returns the intervalo.
     * @uml.property  name="intervalo"
     */
	public static long getIntervaloMs() {
		return intervaloMS;
	}

	/**
     * Setter of the property <tt>intervalo</tt>.
     * @param intervalo  The intervalo to set.
     * @uml.property  name="intervalo"
     */
    public static void setIntervaloMS(final long lIntervaloMS) {
		Rellotge.intervaloMS = lIntervaloMS;
	}

    /**
     * @return the data_actual
     */
    public static Date getDataActual() {
        return dataActual;
    }

    /** 
     * Data que agafarem per actualizar la data dels intervals cada vegada 
     * que els notifica que ha cambiat.
     * @uml.property name="data_actual"
     */
    public static void setDataActual(final Date dDataActual) {
        Rellotge.dataActual = dDataActual;
    }
    
   
	 //********************** Metodes de la Classe **********************

	
    
    /*
     a timertask is executed by a timer, which is basically an executor thread.
    you can use a timertask to schedule a short (execution-wise) code to 
    be executed at a certain time or repeatedly.
    a thread would be used for long (execution wise) code, like blocking 
    networking, 
    gps, lengthy calculations or similar.
     */
     
    /**
     * Encarregat de iniciar el rellotge,
     * Realitza la creaci� del objecte Timer
     * per a cada 2 segons notifiqui als observadors. 
     * 
     * @uml.property name = "iniciar"
    */
    
	public void iniciar() {
	
		on = true;
		if (temps == -1) {
		   
		    setDataInicial(new Date());
		    // System.out.println("Timer no estaba creado");
			timer = new Timer();
			timer.scheduleAtFixedRate(notificaObservadors, 0 , INTERVALO_MS);
			
		}
		temps = 0;
		
	} 
	
	 /**
     * Cridat per el timer del m�tode iniciar,
     * realizta la actualitzaci� de la {@link dataActual},
     * incrementa 2 segons {@link intervaloMS} i
     * notifica als observadors del rellotge.
     * @uml.property name = "run"
    */
	private TimerTask notificaObservadors = new TimerTask() {
	    
        public void run() {
           // System.out.println("estado del on en el reloj:"+on);
	        if (on) {
	            //System.out.println("Reloj notificar observadores");
	            setDataActual(new Date());
	            setChanged();
	            notifyObservers();
	            intervaloMS =  INTERVALO_MS;
	        } 
	        
	    }
	};
	
	/**
	 * El objectiu es aturar el rellotge
	 * es a dir tots els intervals que 
	 * observen el rellotge s'aturaran 
	 * {@value on} a False.
	 */
	public void parar() {
	   
	   on = false;
	   this.setOn(on);
	   timer.cancel(); //eliminamos el timer actual
	   
	}

	/**
	 * Realitza el patr� de disseny Singleton.
	 * controla que nomes pugui crear un objecte 
	 * {@link Rellotge}
     * @return the instancia
     */
    public static Rellotge getInstancia() {
        if (instancia == null) {
            instancia = new Rellotge();
        }
        return instancia;
    }

    /**
     * @param instancia the instancia to set
     */
    public static void setInstancia(final Rellotge rInstancia) {
        Rellotge.instancia = rInstancia;
    }

    public static Date getDataInicial() {
        return dataInicial;
    }

    public static void setDataInicial(Date dDataInicial) {
        dataInicial = dDataInicial;
    }

    /**
	 * @uml.property  name="instancia"
	 */
	private static Rellotge instancia = null;

	
	
}
